# -*- coding: utf-8 -*-
'''
Created on 2019年3月24日

@author: guety
'''
import os
import copy
import datetime
import logging
import sys
import datetime
import random
import numpy as np

from  CAR import CAR
from CROSS import CROSS
from ROAD import ROAD
from DATA import DATA


np.random.seed(951105)
ALL_TIME=500
graph=[[sys.maxsize] * 65 for i in range(65)]
road_map=[[sys.maxsize] * 65 for i in range(65)]


def dijkstra(startIndex):
    """
    求解各节点最短路径，获取path，和cost数组，
    path[i] 表示vi节点的前继节点索引，一直追溯到起点。
    cost[i] 表示vi节点的花费
    """
    lenth = len(graph)
    max=sys.maxsize
    path = [0] * lenth
    cost = [0] * lenth
    v = [0] * lenth
    # 初始化 path，cost，V
    for i in range(lenth):
        if i == startIndex:
            v[startIndex] = 1
        else:
            cost[i] = graph[startIndex][i]
            path[i] = (startIndex if (cost[i] < max) else -1)
    # print v, cost, path
    for i in range(1, lenth):
        minCost = max
        curNode = -1
        for w in range(lenth):
            if v[w] == 0 and cost[w] < minCost:
                minCost = cost[w]
                curNode = w
        # for 获取最小权值的节点
        if curNode == -1: break
        # 剩下都是不可通行的节点，跳出循环
        v[curNode] = 1
        for w in range(lenth):
            if v[w] == 0 and (graph[curNode][w] + cost[curNode] < cost[w]):
                cost[w] = graph[curNode][w] + cost[curNode] # 更新权值
                path[w] = curNode # 更新路径
        # for 更新其他节点的权值（距离）和路径
    return path



class simulation(object):
    def __init__(self):
        self.dead = False
    def step(self):
        print("time:%d"%DATA.TIME)
        for crossId in DATA.CROSSNAMESPACE:#将所有车辆设置为等待状态
            DATA.CROSSDICT[crossId].setDone(False)
        # print("pre-movement...")
        """
        移动可以行走的，并且行走的最远距离没有到达十字路口的车辆
        """
        for road in DATA.ROADNAMESPACE:
            DATA.ROADDICT[road].stepInit()
        # print("while loop...")
        """
        开始调度十字路口的车辆
        """
        unfinishedCross = DATA.CROSSNAMESPACE
        while unfinishedCross.__len__() > 0:
            self.dead = True
            nextCross = []
            for crossId in unfinishedCross:
                cross = DATA.CROSSDICT[crossId]
                cross.step()
                if not cross.__done__():
                    nextCross.append(crossId)
                if cross.__update__() or cross.__done__(): #如果两次路口状态发生变化，那么就不会锁死
                    self.dead = False
            unfinishedCross = nextCross
            if self.dead is True:
                break
            #     pass
            # assert self.dead is False , print("dead lock in", unfinishedCross)
        # print("car pulling away from carport")
        for i in range(DATA.CROSSNAMESPACE.__len__()):
            crossId = DATA.CROSSNAMESPACE[i]
            for roadId in DATA.CROSSDICT[crossId].__validRoad__():
                DATA.ROADDICT[roadId].setBucket(crossId)
            DATA.CROSSDICT[crossId].outOfCarport()
        if self.dead is True:
            print("dead lock in", unfinishedCross)
            sys.exit
    def simulate(self):
        while True:
            # try:
            self.step()
            # except :
            #     return 0
            # visualize.drawMap()
            if DATA.CARDISTRIBUTION[2]==DATA.CARNAMESPACE.__len__():
                print("happy",DATA.CARDISTRIBUTION[2])
                break
            if self.dead:
                break
            DATA.TIME +=1
        return  DATA.TIME 



def main():
    if len(sys.argv) != 5:
        logging.info('please input args: car_path, road_path, cross_path, answerPath')
        exit(1)

    car_path = sys.argv[1]
    road_path = sys.argv[2]
    cross_path = sys.argv[3]
    answer_path = sys.argv[4]

    logging.info("car_path is %s" % (car_path))
    logging.info("road_path is %s" % (road_path))
    logging.info("cross_path is %s" % (cross_path))
    logging.info("answer_path is %s" % (answer_path))

    carInfo = open(car_path, 'r').read().split('\n')[1:]
    roadInfo = open(road_path, 'r').read().split('\n')[1:]
    crossInfo = open(cross_path, 'r').read().split('\n')[1:]


    #初始化道路
    for line in roadInfo:
        id_, length_, speed_, channel_, from_, to_, isDuplex_ = line.replace(' ', '').replace('\t', '')[1:-1].split(',')
        DATA.ROADNAMESPACE.append(int(id_))
        DATA.ROADDICT[int(id_)] = ROAD(int(id_), int(length_), int(speed_), int(channel_), int(from_), int(to_),int(isDuplex_))
        if int(isDuplex_)==1:
            graph[int(from_)][int(to_)]=graph[int(to_)][int(from_)]=int(length_)
            # print(router_map[int(from_)][int(to_)],end=" ")
        else:
            graph[int(from_)][int(to_)]=int(length_)
        road_map[int(from_)][int(to_)]=road_map[int(to_)][int(from_)]=int(id_)
    map_dijkstra=[]
    for i in range(65):
        map_dijkstra.append(dijkstra(i))
    
    speed_step=[0,0,0,0,0]
    car_num=0
    for line in carInfo:
        id_, from_, to_, speed_, planTime_ = line.replace(' ', '').replace('\t', '')[1:-1].split(',')
        DATA.CARNAMESPACE.append(int(id_))
        result = []
        temp=int(to_)
        FROM=int(from_)
        path=map_dijkstra[FROM]
        while True:
            result.append(temp)
            if temp != int(FROM):
                if temp >=0:
                    temp=path[temp]
                else:
                    result=[]
                    break
            else:
                break
        router=[]
        for x in range(len(result)-1,1,-1):
            router.append(road_map[result[x-1]][result[x]])
        speed_step[int(int(speed_)/2)]+=1
        car_num+=1
        DATA.CARDICT[int(id_)] = CAR(int(id_), int(from_), int(to_), int(speed_), int(planTime_),router)
    
    
    num_=0
    planTime_setp=[0]
    for i in range(1,5):
        num_+=speed_step[i]
        planTime_setp.append(int((num_/car_num)*ALL_TIME))
    # print(planTime_setp)
    for line in crossInfo:
        id_, north_, east_, south_, west_ = line.replace(' ', '').replace('\t', '')[1:-1].split(',')
        DATA.CROSSNAMESPACE.append(int(id_))
        DATA.CROSSDICT[int(id_)] = CROSS(int(id_), int(north_), int(east_), int(south_), int(west_))

    for i in  DATA.CARDICT:
        index=int(DATA.CARDICT[i]. __speed__()/2)
        planTime_=random.randint(planTime_setp[index-1],planTime_setp[index])
        car_planTime=DATA.CARDICT[i]. __planTime__()
        if car_planTime >planTime_:
            planTime_=ALL_TIME+planTime_
        DATA.CARDICT[i].simulateInit(planTime_)
    
    DATA.CARDISTRIBUTION[0] = DATA.CARNAMESPACE.__len__()
    # **** cross initialization ****#
    for carId in DATA.CARNAMESPACE:
        DATA.CROSSDICT[DATA.CARDICT[carId].__from__()].carportInitial(DATA.CARDICT[carId].__planTime__(), carId)
    # ****Initialization ****#
    # sys.exit()
    DATA.CARNAMESPACE.sort()
    DATA.CROSSNAMESPACE.sort()
    # simulator
    simulate = simulation()
    simulate.simulate()
# to read input file
# process
# to write output file


if __name__ == "__main__":
    starttime = datetime.datetime.now()
    main()
    endtime = datetime.datetime.now()
    print ((endtime - starttime).seconds)
    # cd C:\Users\guety\Documents\VScode\SDK\SDK_python\CodeCraft-2019\src 
    # python CodeCraft-2019.py ../config/car.txt ../config/road.txt ../config/cross.txt ../config/answer.txt


    """

    cd /home/yannick/桌面/SDK_python/CodeCraft-2019/src && python CodeCraft-2019.py ../config/car.txt ../config/road.txt ../config/cross.txt ../config/answer.txt

    """